/*! \file abstractnode.h
	\author HiddenSeeker

	Defines an abstract syntax node
*/
#include<stdio.h>
#include"../lexerparser/lp_defs.h"
#include"../lexerparser/recovery.h"
#pragma once


#define UNKNOWN_TYPE "<UNKNOWN>"

class ParentData;
/*! Declares an stream data for tree data generation
*/
struct GraphStream
{
 public:
	     FILE *  stream; //!< Stream data for writing
		 int     amount; //!< Amount of nodes

		 /*! Constructs a stream from file stream
			 \param[in] s stream
		 */
		 inline GraphStream(FILE * s) { stream=s; amount=0; }
		 /*! Closes a stream
		 */
		 inline ~GraphStream() {if (stream) fclose(stream); }
};

extern const char * current_filename;
/*! Declares an abstract syntax node
*/
class AbstractNode
{
 private:
	     int m_number; //!< Declares a node unique number in tree
		 bool m_ownage; //!< Determines whether object determines ownage of it's data
		 std::string m_filename; //!< Filename, where it belongs to
 protected:
 	     int m_line;   //!< Line position
		 int m_pos;    //!< Position 
		 /*! Determines, whether class is owning self data.
		 */
		 inline bool isOwningData() { return m_ownage; }
 public:
	    inline void setLocation(const YYLTYPE & pos)
		{
			m_line=pos.first_line;
			m_pos=pos.first_column;
		}
		inline int line()     const  { return m_line; }
		inline int position() const  { return m_pos;  }
		inline const std::string & filename() const { return m_filename;}
		inline std::string & filename()  { return m_filename;}
		inline int & line()      { return m_line; }
		inline int & position()  { return m_pos;  }
		/*! Checks if returning result
		 */
		virtual bool   isResultReturn();
		/*! Defines an abstract node with specifies position
			\param[in] pos position
		*/
		AbstractNode(const YYLTYPE & pos) { m_line=pos.first_line; m_pos=pos.first_column; m_ownage=false; push_node(this); m_filename=current_filename; }
		/*! Accepts a stream, incrementing it's amount
		   \param[in] s stream node
		*/
		inline void accept(GraphStream * s) { m_number=s->amount; ++(s->amount); }
		/*! Declares a number of node
			\return node
		*/
		inline int number() { return m_number; }
		/*! Owns every data by node
		*/
		inline void own() { m_ownage=true; }
		/*! Disowns every data by node
		 */
		inline void disown() { m_ownage=false; }
		/*! Writes a node data to stream
		*/
		virtual void write(GraphStream * s)=0;
		/*! Transforms a code, if needed to
			\return true on success
		 */
		virtual bool transformCode(ParentData * data); 
		/*! Transforms a code, if needed to
			\return true on success
		 */
		virtual bool checkLogic(ParentData * data); 
		/*!  Checks is node can be assigned
		 */
		virtual bool isLValue(ParentData * data);
		/*!  Checks, whether it's identifier
		 */
		virtual bool isIdentifier();
		/*! Checks common errors
		 */
		virtual void checkCommonErrors(ParentData * data);
		/*! Transforms from assignment
		 */
		virtual bool canBeTransformedFromAssignment(ParentData * data, bool * error);
		/*! Returns false
		 */
		virtual bool isOperator();


		/*! Fills a constant table for method
		 */
		virtual void fillConstant(ParentData * data);

		/*! Produces a code for method
		 */
		virtual void produceCode(ParentData * data);
		/*! Returns unknown type
		 */
		virtual std::string getType(ParentData * data);
		/*! Negates a node data
		*/
		virtual AbstractNode * negate(const YYLTYPE & pos);
		//! Destructor
		virtual ~AbstractNode();
};
